/* 
 * File:   ClientSocket.cpp
 * Author: mauro
 * 
 * Created on 25 de septiembre de 2014, 19:51
 */

#include "ClientSocket.h"

ClientSocket::ClientSocket() {

}

int ClientSocket::initSocket() {
    //creacion del socket    
    this->socket = ::socket(AF_INET, SOCK_STREAM, 0);
    return this->socket;
}

int ClientSocket::connect(char *ip, int port) {
    this->serverAddress.sin_family = AF_INET;
    this->serverAddress.sin_port = htons(port); //host-to-network-short    
    //asigno la direccion
    this->serverAddress.sin_addr.s_addr = inet_addr(ip);
    //    ::memset (&(this->serverAddress.sin_zero),8); //poner a cero el resto de la estructura.            
    int len = sizeof (this->serverAddress);
    int estado = ::connect(this->socket, (struct sockaddr *) & this->serverAddress, len);
    return estado;
}

int ClientSocket::send(void *cad, int length) {
    int estado = ::send(this->socket, cad, length, 0);
    return estado;
}

int ClientSocket::sendAll(void* buf, int len) {
    int total = 0;
    int bytesLeft = len;
    int n = 0;
    while (total < len) {
        n = this->send(buf + total, len);
        if (n == -1) {
            return n;
        }
        total += n;
        bytesLeft -= n;
    }
    return total;
}

int ClientSocket::recvTimeOut(void* buf, int len, int timeOut) {
    fd_set fds; //Descriptor de fichero.
    int n;
    struct timeval tv; //permite establecer un periodo maximo de espera.    
    FD_ZERO(&fds); //borra un conjunto de descriptores de fichero.    
    FD_SET(this->socket, &fds); //añade socket al conjunto.
    //Estructura timeval del temporizador
    tv.tv_sec = timeOut; //numero de seg que quiero esperar. 
    
    tv.tv_usec = 0; // numero de microsegundos. (hay 1.000.000 de microseg en un seg)
    //esperar hasta que se reciban datos o venza el temporizador.
    n = select(this->socket + 1, &fds, NULL, NULL, &tv);
    if (n == 0) return -2; //el temporizador ha vencido!
    if (n == -1) return -1; //error
    //los datos deben estar ahí, así que llamo a normalmente a recvAll()
    return this->receiveAll(buf, len); //return 0, se desconecto el cliente.
    
}

int ClientSocket::receive(void *cad, int length) {
    int error = recv(this->socket, cad, length, 0);
    return error;
}

int ClientSocket::receiveAll(void *buf, int length) {
    int total = 0;
    int bytesLeft = length;
    int cant = 0;
    while (total < length) {
        //        cout<<"recv !!! "<<endl;
        cant = this->receive(buf + total, length);
        if (cant == -1) {
            break;
        }
        total += cant;
        bytesLeft -= cant;
    }
    return total;

}

void ClientSocket::close() {
    //ver esto, para cerrar un socket.
    shutdown(this->socket, 2);
    ::close(this->socket);
    //    this->socket = -1;

}

ClientSocket::~ClientSocket() {
//    cout << "Destructor de Clienteeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee" << endl;
}

